package com.guoxw.ibinderdemo.server;

import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.guoxw.ibinderdemo.Book;
import com.guoxw.ibinderdemo.proxy.Proxy;

import java.util.List;

public abstract class Stub extends Binder implements BookManager {

    private static final String DESCRIPTOR = "com.guoxw.ibinderdemo.server.BookManger";

    public Stub(){

        this.attachInterface(this,DESCRIPTOR);

    }

    public static BookManager asInterface(IBinder iBinder){
        if(iBinder == null){
            return null;
        }

        //查找 Binder 本地对象
        //如果找到了就说明 Client 和 Server 在同一进程，那么这个 binder 本身就是 Binder 本地对象，可以直接使用。
        //否则说明是 binder 是个远程对象，也就是 BinderProxy
        IInterface iin = iBinder.queryLocalInterface(DESCRIPTOR);

        //同一进程
        if (iin!=null&&iin instanceof BookManager){
            //直接返回binder对象
            return (BookManager) iin;
        }
        //不在统一进程，返回远端代理
        return new Proxy(iBinder);
    }

    /**
     * 此方法用于返回当前Binder对象
     * @return
     */
    @Override
    public IBinder asBinder() {
        return this;
    }

    @Override
    protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {

        switch (code){
            case INTERFACE_TRANSACTION:

                reply.writeString(DESCRIPTOR);
                return true;
            case TRANSAVTION_getBooks:

                data.enforceInterface(DESCRIPTOR);
                List<Book> result = this.getBooks();
                //特殊功能，用于在包裹正面书写信息，表明未发生异常
                reply.writeNoException();
                //实体类需要实现序列化
                reply.writeTypedList(result);

                return true;
            case TRANSAVTION_addBook:
                data.enforceInterface(DESCRIPTOR);

                Book book = null;
                if(data.readInt()!=0){
                    book = Book.CREATOR.createFromParcel(data);
                }

                this.addBook(book);
                reply.writeNoException();

                return true;
        }

        return super.onTransact(code, data, reply, flags);
    }


    public static final int TRANSAVTION_getBooks = IBinder.FIRST_CALL_TRANSACTION;
    public static final int TRANSAVTION_addBook = IBinder.FIRST_CALL_TRANSACTION + 1;

}
